//
//  BaseRequest.swift
//  Exchange
//
//  Created by rui on 2018/4/16.
//  Copyright © 2018年 common. All rights reserved.
//

import Foundation
import UIKit

protocol RequestCallBack: class {
    func requestDidSucess(_ request: BaseRequest)
    func requestDidFail(_ request: BaseRequest)
}

///数据整理
protocol RequestDataReformer: class {
    func reform(_ request: BaseRequest,_ data: [String:Any]? )
}
///数据校验器
protocol RequestDataValidator: class {
    func reponseIsValid(_ request: BaseRequest,_ data: [String:Any]? ) -> Bool
    func requestParamsIsValid(_ request: BaseRequest,_ data: [String:Any]? ) -> Bool
}
///请求参数源
protocol RequestParamSource: class {
    func requestParams(_ request: BaseRequest) -> [String:Any]?
}

enum RequestErrorType {
    case `default`
    case  success
    case  noContent
    case  params
    case  timeOut
    case  badnetwork
    case  server
    
    func errorMsg() -> String {
        switch self {
        case .badnetwork:
            return kText("当前无网络,请检查网络")
        case .timeOut:
            return kText("连接超时,请检查网络环境")
        case .params:
            return kText("数据异常,请稍候再试")
        case .default:
            return kText("当前无网络,请检查网络")
        case .server:
            return kText("服务器响应异常,请稍后重试")
        default:
            return ""
        }
    }
}


class BaseRequest {
    weak var delegate: RequestCallBack?
    weak var dataReformer: RequestDataReformer?
    weak var dataValidator: RequestDataValidator?
    weak var paramSource: RequestParamSource?

    var response : Response?
    var errorMsg: String = ""
    var requestId = 0
    init() {
        self.dataValidator = self
    }
    func loadData() {
        if self.openIndicator() {
            CYMBShow.openIndicator(message: nil, view: nil)
        }
        //判断时间是否需要刷新token
        APPRefreshTonken.default.compareTimeLimit()
        var params = self.paramSource?.requestParams(self)
        if params == nil {
            params = [String:Any]()
        }
        loadData(params!)
    }
    
    func loadData(_ params: [String: Any]) {
        if self.dataValidator?.requestParamsIsValid(self, params) == true {
            ///网络状态
            let isReachable = NetworkMonitor.default.isReachable
            if isReachable {
                requestId = RequestClient.default.request(serviceIdentifier: server(), httpMethod: self.method(), params: params, methodName: path(), timeoutInterval: timeout(), success: { (res) in
                    self.requestSucess(res)
                }) { (res) in
                    self.requestFailed(res, .server)
                }
            }else {
                self.requestFailed(nil, .badnetwork)
            }
        }else {
            self.requestFailed(nil, .params)
        }
    }
    
    func requestFailed(_ response: Response?,_ errorType: RequestErrorType) {
        if self.openIndicator() {
            CYMBShow.colseIndicator()
        }
        self.errorMsg = errorType.errorMsg()
        self.delegate?.requestDidFail(self);
    }
    
    func requestSucess(_ response: Response?) {
        if self.openIndicator() {
            CYMBShow.colseIndicator()
        }
        if let data = response?.value as? [String:Any] {
            let status = data["status"] as? Int ?? 0
            if  status != 200 {
                let error = data["error"] as? String ?? ""
                let msg = data["message"] as? String ?? ""
                self.errorMsg = msg.count > 0 ? msg : error
                self.response = response
                self.delegate?.requestDidFail(self)
                
                if status == 401 {
                    if !AppInfo.default.isLogin {
                        if self.path() != Api.Mine.logout  {
                        let controller:UIViewController =  CYMBShow.currentController()!
                        controller.navigationController?.popToRootViewController(animated: true)
                        }
                    }else {
                        if CYMBShow.currentController() != nil {
                            Alert.default.delegate = self
                            Alert.default.show(title: kText("登录已失效,请退出重新登录"), message:"", actions: [kText("取消"),kText("重新登录")], from: CYMBShow.currentController()!) {
                                
                            }
                            AppInfo.default.isLogin = false
                            return
                        }else {
                            CYMBShow.showMessage(kText("登录已失效,请退出重新登录"))
                            return
                        }
                    }
                }
                return
            }
        }
        if let flag = self.dataValidator?.reponseIsValid(self, response?.value as? [String : Any]), flag == true {
            self.delegate?.requestDidSucess(self)
            self.dataReformer?.reform(self, response?.value as? [String : Any])
        }else {
            requestFailed(response, .noContent)
        }
    }
    
    func cancelRequest() {
        if requestId != 0 {
            RequestClient.default.cancelRequest(taskIdentifier: requestId)
        }
    }
    
    ///Requestable
    func path() -> String {
        return ""
    }
    func method() -> HTTPMethodType {
        return .post
    }
    func timeout() -> TimeInterval {
        return 10
    }
    func server() -> Service {
        return Service.app
    }
    func useCache() -> Bool {
        return false
    }
    func openIndicator() -> Bool {
        return false
    }
}

extension BaseRequest : Requestable {}

extension BaseRequest : RequestDataValidator {
    func reponseIsValid(_ request: BaseRequest,_ data: [String:Any]? ) -> Bool {
        return true
    }
    func requestParamsIsValid(_ request: BaseRequest,_ data: [String:Any]? ) -> Bool {
        return true
    }
}
extension BaseRequest : AlertDelegate {
    func alert(didSelected title: String?) {
        if title == kText("重新登录") {
            let controller:UIViewController =  CYMBShow.currentController()!
            let pop = LoginViewController()
            pop.isNeedPop = true
            controller.navigationController?.pushViewController(pop, animated: true)
        }else {
            let controller:UIViewController =  CYMBShow.currentController()!
            controller.navigationController?.popToRootViewController(animated: true)
        }
        
    }
}

